package com.dc.zuul.filter;

import com.dc.zuul.build.GatewayDirector;
import com.dc.zuul.mapper.BlacklistMapper;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringEscapeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

@Slf4j
@Component
public class GatewayFilter extends ZuulFilter {

    @Autowired
    private BlacklistMapper blacklistMapper;

    @Autowired
    private GatewayDirector gatewayDirector;


    //@Autowired
    //private ResponsibilityClient responsibilityClient;

    @Override
    public String filterType() {
        return "pre";  //请求之前  实现拦截
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    /**
     * 请求之前拦截处理
     *
     * @return
     * @throws ZuulException
     */
    @Override
    public Object run() throws ZuulException {
        RequestContext ctx = RequestContext.getCurrentContext();
        //1、获取请求对象
        HttpServletRequest request = ctx.getRequest();
        //2、获取客户端真实IP地址
        String ipAddr = getIpAddr(request);
        //if (ipAddr.equals("127.0.0.1")) {
        //    resultError(ctx, "ip" + ipAddr + ",Insufficient access");
        //}
        //查询数据库
        //3、黑白名单限制
        // DcBlacklist blacklist = blacklistMapper.findBlacklist(ipAddr);
        // if (blacklist != null) {
        //     resultError(ctx, "ip" + ipAddr + ",Insufficient access");
        // }
        // //4、验证签名拦截
        // Map<String, String> verifyMap = SignUtil.toVerifyMap(request.getParameterMap(), false);
        // if (!SignUtil.verify(verifyMap)) {
        //     resultError(ctx, "ip:" + ipAddr + ",Sign fail;");
        // }
        // 将步骤3 4 替换成设计模式。注意是否开启
        gatewayDirector.direcot(ctx, ipAddr, ctx.getResponse(), request);
        //responsibilityClient.responsibility();  责任链

        //5、XSS SQL 注入拦截
        // 3. 过滤请求参数、防止XSS攻击
        Map<String, List<String>> filterParameters = filterParameters(request, ctx);
        ctx.setRequestQueryParams(filterParameters);
        //6、获取响应对象
        //HttpServletResponse response = ctx.getResponse();
        //转发服务
        return null;
    }
    /*******************************---------------------------------***/
    /**
     * 获取Ip地址
     *
     * @param request
     * @return
     */
    public String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    private void resultError(RequestContext ctx, String errorMsg) {
        ctx.setResponseStatusCode(401);
        ctx.setSendZuulResponse(false);  //网关响应为false  不会转发
        ctx.setResponseBody(errorMsg);
    }

    /**
     * 过滤参数  防止 XXL 攻击
     */
    private Map<String, List<String>> filterParameters(HttpServletRequest request, RequestContext ctx) {
        Map<String, List<String>> requestQueryParams = ctx.getRequestQueryParams();
        if (requestQueryParams == null) {
            requestQueryParams = new HashMap<>();
        }
        Enumeration em = request.getParameterNames();
        while (em.hasMoreElements()) {
            String name = (String) em.nextElement();
            String value = request.getParameter(name);
            ArrayList<String> arrayList = new ArrayList<>();
            // 将参数转化为html参数 防止xss攻击 < 转为&lt;
            arrayList.add(StringEscapeUtils.escapeHtml(value));
            requestQueryParams.put(name, arrayList);
        }
        return requestQueryParams;
    }

    // ip地址存在一个问题
    private void resultInsufficientAuthority(RequestContext ctx, String errorMsg) {
        baseResultErrorBase(ctx, 401, errorMsg);
    }

    private void baseResultErrorBase(RequestContext ctx, int code, String errorMsg) {
        ctx.setResponseStatusCode(500);
        // 网关响应为false 不会转发服务
        ctx.setSendZuulResponse(false);
        ctx.setResponseBody(errorMsg);
    }

}

